<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>

	<script type="text/javascript">

	
		function factorial(x){
			if(x<1) return 1;
			return x * factorial(x-1);
		}
		
		document.write("<br> <br> <b> FUNCTION BASICS: </b> ");
		document.write("<br>");
		document.write(" Factorial 5: " + factorial(5));
	

		document.write("<br> <br> <b> *** METHODS *** </b>");
		document.write("<br> Function that is stored in a property of an object. Difference respect function: context execution!");
		document.write("<br>");
		
		document.write("<br> <b> 1) Method Invocation: </b>");
		//Method Invocation sample		
		var calculator = { //object literal
				operand1 : 1,
				operand2 : 1,
				add: function (x){					
					document.write("<br> <i>add()</i> is a property accessor of <i>Calculator</i> object");
					document.write("<br> Method can use <i>this</i> to refer to object because the Object becomes the <i>Invocation Context</i>");
					return this.operand1 + this.operand2 + x;					
				}				
		};		
		
		document.write(" <br> Calculator.add(): " + calculator.add(5));
		document.write("<br>");
		
		document.write("<br> <b> 2) <i>this</i> scope: </b> nested functions");
		
		var o = {				
			m : function(){
				var self = this;
				document.write("<br> testing where <i>this</i> is visible");
				
				if(this == o){
					document.write("<br>this visible: true" );
				}else{
					document.write("<br>this visible: false" );
				}
				
				f();
				
				function f(){
					document.write("<br> nested function --> " );
					if(this == o){
						document.write("<i> this visible:</i> true   " );
					}else{
						document.write("<i>this visible:</i> false   " );
					}
					
					if(self == o){
						document.write("<i>self visible:</i> true" );
					}else{
						document.write("<i>self visible:</i> false" );
					}
					
				}
				
			}	
				
		};
		
		o.m();
		
		
		document.write("<br> <br> <b> 3) Arguments: </b>");
		document.write("Arguments missing: treated as <i>undefined</i>");
		document.write("Arguments exceding: ignored as <i>undefined</i>");
		document.write("Arguments: stored in an <i>array-like object</i>");
		
		
		
		document.write("<br> <br> <b> 4) Closures: </b>");
		//3 CLosures	
		document.write("<br> The combination of a function object and a scope (a set of variable bindings)"
				+ " in which the functions variables are resolved is called a closure");
		
		
		document.write("<br> <br> <i> Basic sample 1:  </i>");
		
		
		var scope = "global scope";
		
		function checkScope(){
			var scope = "local scope";
			function f(){return scope;}
			return f();						//This returns the value - So, the function is executed in order to get the value. 
		}
		
		document.write("<br> Which scope (get value)? " + checkScope());
		
		
		function checkScope2(){
			var scope = "local scope";
			function f(){return scope;}
			return f;						//This returns the function itself (which is a JS object, actually) - 
											//in order to get the value we manually need to call the objecy method 
		}		
		
		document.write("<br> Which scope? (get function) " + checkScope2());
		document.write("<br> WE execute the function to get the value: " + checkScope2()());
		
		
		document.write("<br> <br> <i> Closure sample 1:  </i>");  
		
		// Return an array of functions that return the values 0-9
		function constfuncs() {
			var funcs = [];
			
			for(var i = 0; i < 10; i++){
				funcs[i] = function() { return i; };
			}				
				
			document.write("<br> funcs: " + funcs);
			return funcs;
		}
		
		var funcs = constfuncs();
		document.write("<br> Function Return[0]: " + funcs[0]()); // What does this return?
		document.write("<br> Function Return[1]: " + funcs[1]());
		 
		
		document.write("<br> For loop creates 10 clousures (defined within same invokation function)" +
				", so they share access to variable i");
				
				
		document.write("<br> <br> <i> Closure sample 2 </i>"); 
				
		// This function returns a function that always returns v
		function constfunc2(v) { return function() { return v; }; }
		
		// Create an array of constant functions:
		var funcs2 = [];
		for(var i = 0; i < 10; i++){			
			if(i<2) document.write("<br> i: " + i + " constfunc: " + constfunc2(i));
			funcs2[i] = constfunc2(i);
		}
		
		document.write("<br> Function Return2[0]: " + funcs2[0]());
		document.write("<br> Function Return2[1]: " + funcs2[1]());
			
		
		document.write("<br> <br> <i> Closure sample 3 </i>");
		
		function say667() {
			  // Local variable that ends up within closure
			var num = 666;
			var sayAlert = function() { document.write(num); }
			num++;
			return sayAlert();
		}
		
		sayNum = say667();
		//sayNum();
		
		
		
		
	</script>
	
	
</body>
</html>